package com.leyou.order.service;

import com.leyou.auth.pojo.UserInfo;
import com.leyou.common.dto.CartDTO;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.pojo.Sku;
import com.leyou.order.client.AddressClient;
import com.leyou.order.client.GoodsClient;
import com.leyou.order.dto.AddressDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.enums.PayState;
import com.leyou.order.interceptor.UserInterceptor;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.mapper.OrderStatusMapper;
import com.leyou.order.pojo.Order;
import com.leyou.order.pojo.OrderDetail;
import com.leyou.order.pojo.OrderStatus;
import com.leyou.order.utils.PayHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.OffsetDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.github.wxpay.sdk.WXPayConstants.FAIL;

/**
 * @author huangxin
 * @date 2019/5/14-21:38
 */
@Service
@Slf4j
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderStatusMapper orderStatusMapper;

    @Autowired
    private GoodsClient goodsClient;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private PayHelper payHelper;

    @Transactional
    public Long createOrder(OrderDTO orderDTO) {
        Order order = new Order();
        //1.新增订单
        long id = idWorker.nextId();
        order.setOrderId(id);
        //创建时间
        order.setCreateTime(new Date());
        //支付类型
        order.setPaymentType(orderDTO.getPaymentType());
        //获取联系人
        UserInfo user = UserInterceptor.getUser();
        order.setUserId(user.getId());
        //昵称
        order.setBuyerNick(user.getUsername());
        //是否评价
        order.setBuyerRate(false);
        //收货人信息
        AddressDTO addressDTO = AddressClient.findById(orderDTO.getAddressId());
        order.setReceiver(addressDTO.getName());
        order.setReceiverAddress(addressDTO.getAddress());
        order.setReceiverCity(addressDTO.getCity());
        order.setReceiverDistrict(addressDTO.getDistrict());
        order.setReceiverMobile(addressDTO.getPhone());
        order.setReceiverState(addressDTO.getState());
        order.setReceiverZip(addressDTO.getZipCode());

        //金额
        //把cartDTO转为map,key为skuId,值为number数量
        Map<Long, Integer> numMap =
                orderDTO.getCarts().stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
        //根据ids查询sku
        Set<Long> ids = numMap.keySet();
        List<Sku> skus = goodsClient.querySkuByIds(new ArrayList<>(ids));

        long totalPay = 0L;

        //准备orderDetail集合
        List<OrderDetail> orderDetailList = new ArrayList<>();

        for (Sku sku : skus) {
            //计算总金额
            Integer num = numMap.get(sku.getId());
            totalPay += sku.getPrice() * num;

            //封装orderDetail
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setImage(StringUtils.substringBefore(sku.getImages(), ","));//只设置一张图片
            orderDetail.setNum(num);
            orderDetail.setOrderId(order.getOrderId());
            orderDetail.setOwnSpec(sku.getOwnSpec());
            orderDetail.setPrice(sku.getPrice());
            orderDetail.setSkuId(sku.getId());
            orderDetail.setTitle(sku.getTitle());
            orderDetailList.add(orderDetail);
        }
        order.setTotalPay(totalPay);
        //实付金额  总金额加邮费减去优惠金额
        order.setActualPay(totalPay + order.getPostFee() - 0);


        //写入数据库
        int count = orderMapper.insertSelective(order);
        if (count != 1) {
            log.error("[创建订单] 创建订单失败,orderId:{}", order.getOrderId());
            throw new LyException(ExceptionEnum.CREATE_ORDER_ERROR);
        }
        //2.新增订单详情
        count = orderDetailMapper.insertList(orderDetailList);
        if (count != orderDetailList.size()) {
            log.error("[创建订单] 创建订单失败,orderId:{}", order.getOrderId());
            throw new LyException(ExceptionEnum.CREATE_ORDER_ERROR);
        }
        //3.新增订单状态
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setCreateTime(order.getCreateTime());
        orderStatus.setOrderId(order.getOrderId());
        orderStatus.setStatus(OrderStatusEnum.UN_PAY.value());
        orderStatusMapper.insertSelective(orderStatus);

        //4.减库存
        List<CartDTO> carts = orderDTO.getCarts();
        goodsClient.decreaseStock(carts);

        return id;
    }

    public Order queryOrderById(Long orderId) {
        //查询订单
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }

        //查询订单详情
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderId);
        List<OrderDetail> orderDetails = orderDetailMapper.select(orderDetail);
        if (CollectionUtils.isEmpty(orderDetails)) {
            throw new LyException(ExceptionEnum.ORDER_DETAIL_NOT_FOUND);
        }
        order.setOrderDetails(orderDetails);

        //查询订单状态
        OrderStatus orderStatus = orderStatusMapper.selectByPrimaryKey(orderId);
        if (orderStatus == null) {
            throw new LyException(ExceptionEnum.ORDER_STATUS_NOT_FOUND);
        }
        order.setOrderStatus(orderStatus);
        return order;
    }

    public String createOrderUrl(Long orderId) {
        //查询订单
        Order order = queryOrderById(orderId);
        //订单状态
        Integer status = order.getOrderStatus().getStatus();
        if (status != OrderStatusEnum.UN_PAY.value()) {
            throw new LyException(ExceptionEnum.ORDER_STATUS_ERROR);
        }
        //支付金额
        Long totalPay = order.getActualPay();
        //商品描述
        String desc = order.getOrderDetails().get(0).getTitle();

        return payHelper.createPayUrl(orderId, totalPay, desc);
    }

    public void handlerNotify(Map<String, String> result) {
        //数据校验
        payHelper.isSuccess(result);
        //校验签名
        payHelper.isValidSign(result);

        //订单金额
        String totalFeeStr = result.get("total_fee");
        //订单号
        String orderId = result.get("out_trade_no");

        if (StringUtils.isBlank(totalFeeStr) || StringUtils.isBlank(orderId)) {
            throw new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
        }
        //获取结果中的金额
        long totalFee = Long.valueOf(totalFeeStr);
        //获取订单
        Order order = orderMapper.selectByPrimaryKey(Long.valueOf(orderId));
        //校验订单金额
        if (totalFee !=/*order.getActualPay()*/ 1L) {
            //金额不符
            throw new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
        }

        //修改订单状态
        OrderStatus status = new OrderStatus();
        status.setStatus(OrderStatusEnum.PAYED.value());
        status.setOrderId(order.getOrderId());
        status.setPaymentTime(new Date());
        int count = orderStatusMapper.updateByPrimaryKeySelective(status);
        if (count != 1) {
            throw new LyException(ExceptionEnum.UPDATE_ORDER_STATUS_ERROR);
        }

        log.info("[订单回调] 订单支付成功");
    }

    public PayState queryOrderState(Long orderId) {
        //查询订单状态
        OrderStatus orderStatus = orderStatusMapper.selectByPrimaryKey(orderId);
        Integer status = orderStatus.getStatus();
        if (status != OrderStatusEnum.UN_PAY.value() && status != OrderStatusEnum.CLOSED.value()) {
            //如果已支付
            return PayState.SUCCESS;
        }

        //如果未支付,但不一定是未支付,必须去微信查询订单状态
        return payHelper.queryPayState(orderId);
    }

    public List<Long> querySkuIdByOrderId(Long orderId) {
        Order order = queryOrderById(orderId);
        List<Long> skuIds = order.getOrderDetails().stream().map(detail -> detail.getSkuId()).collect(Collectors.toList());
        return skuIds;
    }
}
